package com.le.tester.book.concurrentjavafight.l7_2_1;

import java.io.PrintWriter;
import java.util.concurrent.BlockingQueue;

/**
 * createTime：2022/11/17 14:05
 * description：取消机制，对于使用了队列的生产者和消费者，应该有同时取消的机制
 * 有可靠的取消操作
 */
public class LogService {
    private final BlockingQueue<String> queue;

    private final LoggerThread loggerThread;

    private final PrintWriter writer;

    public LogService(BlockingQueue<String> queue, LoggerThread loggerThread, PrintWriter writer) {
        this.queue = queue;
        this.loggerThread = loggerThread;
        this.writer = writer;
    }

    //同时控制take和put()
    private volatile boolean isShutdown;

    //take和put的次数
    private volatile int reservations;

    public void start() {
        loggerThread.start();
    }

    public void stop() {
        synchronized (this) {
            isShutdown = true;
        }
        loggerThread.interrupt();
    }

    public void log(String msg) throws InterruptedException {
        synchronized (this) {
            if (isShutdown) {
                throw new IllegalArgumentException("illegal argument");
            }
            ++reservations;
        }
        queue.put(msg);
    }

    private class LoggerThread extends Thread {

        @Override
        public void run() {
            try {
                while (true) {
                    try {
                        synchronized (LogService.this) {
                            if (isShutdown && reservations == 0) {
                                break;
                            }
                        }

                        String msg = queue.take();
                        synchronized (LogService.this) {
                            --reservations;
                        }
                        writer.println(msg);
                    } catch (InterruptedException e) {
                        System.out.println("retry");
                    }

                }
            } finally {
                writer.close();
            }
        }
    }
}
